﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Documents;
using WpfApplication1;
using System.Windows.Forms;
using System.Windows.Controls;
using Hi_Baidu.Entry.CollectionObject;
using System.IO;
using System.Windows;
using Hi_Baidu.Packet;
using Hi_Baidu.Packet.InPacket.TalkInPacket;
using Hi_Baidu.ListType.DetachMessage;
using Hi_Baidu.Timer.TalkMessage;
using System.Net;
using Hi_Baidu.Cache.CacheObject;
using Hi_Baidu.ListType.DetachImage;
using System.Threading;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using Hi_Baidu.Encrypt;
using Hi_Baidu.Cache;

namespace Hi_Baidu.ProcessModel
{
    /// <summary>
    ///         提供了基础的用户聊天相关操作
    /// </summary>
    class ChatProcessModel : Model
    {
        private static String protocol;
        private static String PackageBody;
        /// <summary>
        ///         此方法用于分析用户聊天内容
        /// </summary>
        public static String Construe(System.Windows.Controls.RichTextBox rtb_TalkMessage, ref int PID)
        {
            String XML_Content = "";

            //得到流文档
            FlowDocument document = rtb_TalkMessage.Document;
            //遍历文档顶级节点
            foreach (Block blk in document.Blocks)
            {
                //当前对象是元素
                if (blk is Paragraph)
                {
                    Paragraph para = blk as Paragraph;
                    //判断元素类型 --> 是图像
                    foreach (Inline line in para.Inlines)
                    {
                        if (line is Run)
                        {
                            Run run = (line as Run);
                            XML_Content += ProtocolFactory.ProtocolFactory.GetTextProtocol(run);
                        }
                        else if(line is InlineUIContainer)
                        {
                            InlineUIContainer IUC = line as InlineUIContainer;
                            if (IUC.Child is ImageExpender)
                            {
                                ImageExpender Img_Exp = IUC.Child as ImageExpender;
                                XML_Content += ProtocolFactory.ProtocolFactory.GetPictireProtocol(Img_Exp, PID, Encoding.Default.GetString(Globle.user.DIC_USERINFO["USERNAME"]));
                                PID++;
                            }
                            else if (IUC.Child is Image)
                            {
                                Image Img = IUC.Child as Image;
                                XML_Content += ProtocolFactory.ProtocolFactory.GetPictireProtocol(Img, PID, Encoding.Default.GetString(Globle.user.DIC_USERINFO["USERNAME"]));
                                PID++;
                            }
                        }
                    }
                }
            }
            return XML_Content;
        }

        /// <summary>
        ///         此方法用于分析用户聊天的输入内容
        /// </summary>
        /// <param name="rtb_TalkMessage" type="System.Windows.Controls.RichTextBox">
        ///     <para>
        ///         聊天输入框句柄
        ///     </para>
        /// </param>
        /// <param name="username" type="string">
        ///     <para>
        ///         用户名
        ///     </para>
        /// </param>
        /// <returns>
        ///     返回布局好的总聊天内容面板
        /// </returns>
        public static Grid Construe(System.Windows.Controls.RichTextBox rtb_TalkMessage, String username)
        {
            //2 x 1的表格
            Grid Total_Grid = new Grid();
            Total_Grid.RowDefinitions.Add(new RowDefinition());
            Total_Grid.RowDefinitions.Add(new RowDefinition());
            Total_Grid = ChatViewModel.AppendMySelfHead(Total_Grid, username);
            WrapPanel WP_UserTalkMessage = new WrapPanel();
            WP_UserTalkMessage.Margin = new Thickness(3, 3, 3, 3);
            WP_UserTalkMessage.Orientation = System.Windows.Controls.Orientation.Horizontal;

            //得到流文档
            FlowDocument document = rtb_TalkMessage.Document;
            //遍历文档顶级节点
            foreach (Block blk in document.Blocks)
            {
                //当前对象是元素
                if (blk is Paragraph)
                {
                    Paragraph para = blk as Paragraph;
                    //判断元素类型 --> 是图像
                    foreach (Inline line in para.Inlines)
                    {
                        if (line is Run)
                        {
                            Run run = (line as Run);
                            TextBlock TB_TextMessage = new TextBlock();
                            TB_TextMessage.Text = run.Text;
                            TB_TextMessage.FontFamily = run.FontFamily;
                            TB_TextMessage.FontSize = run.FontSize;
                            TB_TextMessage.FontStyle = run.FontStyle;
                            WP_UserTalkMessage.Children.Add(TB_TextMessage);
                        }
                        else if (line is InlineUIContainer)
                        {
                            InlineUIContainer IUC = line as InlineUIContainer;
                            if (IUC.Child is ImageExpender)
                            {
                                String ImageToolTip = (IUC.Child as ImageExpender).ToolTip.ToString();
                                if (ImageToolTip.Split(new String[] { "." }, StringSplitOptions.RemoveEmptyEntries).Length <= 1)
                                {
                                    //图片流
                                    PopPictureCache popPictureCache = DeclareCacheManager.popPictureCacheManager.GetMemberByKey(ImageToolTip) as PopPictureCache;
                                    //缓存有效
                                    if (popPictureCache != null)
                                    {
                                        ImageExpender Img_Expender = new ImageExpender();
                                        Img_Expender.Visibility = System.Windows.Visibility.Visible;
                                        Img_Expender.Stretch = System.Windows.Media.Stretch.None;
                                        Img_Expender.Image = popPictureCache.PictureStream;
                                        WP_UserTalkMessage.Children.Add(Img_Expender);
                                        continue;
                                    }
                                    //缓存失败
                                    else
                                    {
                                        Image img_Fail = new Image();
                                        img_Fail.Source = new BitmapImage(new Uri(@"/SysImage/ImageError.gif", UriKind.Relative));
                                        img_Fail.Stretch = System.Windows.Media.Stretch.None;
                                        img_Fail.Visibility = Visibility.Visible;
                                        WP_UserTalkMessage.Children.Add(img_Fail);
                                        continue;
                                    }
                                }
                                else
                                {
                                    //图片
                                    ImageExpender Img_Expender = new ImageExpender();
                                    Img_Expender.Visibility = System.Windows.Visibility.Visible;
                                    Img_Expender.Stretch = System.Windows.Media.Stretch.None;
                                    using (FileStream fs = new FileStream((IUC.Child as ImageExpender).ToolTip.ToString(), FileMode.Open))
                                    {
                                        Stream imageStream = fs;
                                        System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(imageStream);
                                        Img_Expender.Image = bitmap;
                                        WP_UserTalkMessage.Children.Add(Img_Expender);
                                    }
                                }
                                continue;
                            }
                            else if(IUC.Child is Image)
                            {
                                Image img = new Image();
                                img.Stretch = (IUC.Child as Image).Stretch;
                                img.Source = (IUC.Child as Image).Source;
                                WP_UserTalkMessage.Children.Add(img);
                                continue;
                            }
                        }
                    }
                }
            }
            Total_Grid.Children.Add(WP_UserTalkMessage);
            Grid.SetRow(WP_UserTalkMessage, 1);
            return Total_Grid;
        }

        /// <summary>
        ///         发送聊天信息到指定好友
        /// </summary>
        /// <param name="TalkContent" type="string">
        ///     <para>
        ///         聊天内容
        ///     </para>
        /// </param>
        /// <param name="username" type="string">
        ///     <para>
        ///         用户名
        ///     </para>
        /// </param>
        /// <param name="friend" type="Hi_Baidu.Entry.CollectionObject.Friend">
        ///     <para>
        ///         好友对象
        ///     </para>
        /// </param>
        public static void SendTalkMessage(String TalkContent, String username, Friend friend)
        {
            byte[] talkContent = Encoding.Default.GetBytes(TalkContent);
            //可以直接传送
            if (talkContent.Length <= 512)
            {
                byte[] Username = Encoding.Default.GetBytes(username);
                byte[] UsernameLength = BitConverter.GetBytes(Username.Length);
                byte[] TalkContentLength = BitConverter.GetBytes(talkContent.Length);
                byte[] packagebody = new byte[Username.Length + talkContent.Length + 8];
                Offset = 0;
                Array.ConstrainedCopy(UsernameLength, 0, packagebody, Offset, 4);
                Offset += 4;
                Array.ConstrainedCopy(Username, 0, packagebody, Offset, Username.Length);
                Offset += Username.Length;
                Array.ConstrainedCopy(TalkContentLength, 0, packagebody, Offset, 4);
                Offset += 4;
                Array.ConstrainedCopy(talkContent, 0, packagebody, Offset, talkContent.Length);
                Offset += talkContent.Length;

                String TALK_SESSION = Encrypt_HASH.HashString(DateTime.Now.ToString() + ":" + friend.Username);
                //通过命令工厂得到命令协议
                byte[] protocol1 = ProtocolFactory.ProtocolFactory.ReGetProtocolToTalkMessage("TalkMessage",
                                                                       (int)Packet.Protocol.TALK_OUT_NetworkCommand.TOTAL_TALK_MESSAGE,
                                                                       (int)Packet.Protocol.NetworkProtocol.TALK_MESSAGE,
                                                                       packagebody,
                                                                       ProtocolFactory.ProtocolFactory.ACK.Yes,
                                                                       ProtocolFactory.ProtocolFactory.ENCRYPT.No,
                                                                       TALK_SESSION);
                NetControl.Send(protocol1, friend.TalkPort, friend.IpAddress);
                //打入超时队列
                TalkMessageTimeOutEvent TTOE = new TalkMessageTimeOutEvent(friend, TALK_SESSION, 5000, 1);
                Globle.timeoutTimerManager.InstallTimer(TTOE);
            }
            //自动分包传送
            else
            {
                DetachSendTalkMessage(TalkContent, username, friend);
            }
        }

        /// <summary>
        ///     分包发送聊天信息
        /// </summary>
        /// <param name="TalkContent" type="string">
        ///     <para>
        ///         聊天内容 - XML格式
        ///     </para>
        /// </param>
        /// <param name="username" type="string">
        ///     <para>
        ///         用户名
        ///     </para>
        /// </param>
        /// <param name="friend" type="Hi_Baidu.Entry.CollectionObject.Friend">
        ///     <para>
        ///         好友对象
        ///     </para>
        /// </param>
        public static void DetachSendTalkMessage(String TalkContent, String username, Friend friend)
        {
            using (MemoryStream MS_DetachMessage = new MemoryStream())
            {
                MS_DetachMessage.Write(Encoding.Default.GetBytes(TalkContent), 0, Encoding.Default.GetBytes(TalkContent).Length);
                MS_DetachMessage.Flush();
                MS_DetachMessage.Position = 0;
                int ReadCount = 0;
                byte[] Content = new byte[512];
                int TotalPackageCount = (int)Encoding.Default.GetBytes(TalkContent).Length / 512;
                double _Count = Encoding.Default.GetBytes(TalkContent).LongLength / 512.00;
                int _temp = (int)_Count;
                if (_Count > _temp && _Count < _temp + 1)
                {
                    TotalPackageCount = _temp + 1;
                }
                else
                {
                    TotalPackageCount = _temp;
                }
                int PackageId = 1;
                String TALK_SESSION = Encrypt_HASH.HashString(DateTime.Now.ToString() + ":" + friend.Username);
                //分块读取数据
                while ((ReadCount = MS_DetachMessage.Read(Content, 0, 512)) > 0)
                {
                    byte[] content = new byte[ReadCount];
                    Array.ConstrainedCopy(Content, 0, content, 0, ReadCount);

                    //得到协议
                    byte[] protocol1 = ProtocolFactory.ProtocolFactory.DetachTalkMessageProtocol(
                        "DetachTalkMessage",
                        (int)Protocol.TALK_OUT_NetworkCommand.DETACH_TALK_MESSAGE,
                        (int)Protocol.NetworkProtocol.TALK_MESSAGE,
                        Encoding.Default.GetBytes(username),
                        Encoding.Default.GetBytes(friend.Username),
                        Encoding.Default.GetBytes(TALK_SESSION),
                        content,
                        BitConverter.GetBytes(PackageId),
                        BitConverter.GetBytes(TotalPackageCount), 
                        ProtocolFactory.ProtocolFactory.ACK.No,
                        ProtocolFactory.ProtocolFactory.ENCRYPT.No);
                    //发送当前封包片
                    NetControl.Send(protocol1, friend.TalkPort, friend.IpAddress);
                    PackageId++;
                }
                //打入超时队列
                TalkMessageTimeOutEvent TTOE = new TalkMessageTimeOutEvent(friend, TALK_SESSION, 2500, 1);
                Globle.timeoutTimerManager.InstallTimer(TTOE);
            }
        }

        public static void ProcessDetachMessage(Detach_TalkMessagePacket inpackage)
        {
            bool IS_FOUND = false;
            TYPE_DETACH_MESSAGE temp_message = null;
            foreach (TYPE_DETACH_MESSAGE message in Globle.LIST_DetachMessageCollection)
            {
                if (message.Session == inpackage.GetSession())
                {
                    IS_FOUND = true;
                    temp_message = message;
                    break;
                }
            }

            //找到了
            if (IS_FOUND)
            {
                //最后一个封包片 --> 插入
                if (inpackage.GetPackageId() == inpackage.GetTotalPackageCount())
                {
                    ChatProcessModel.ACK_SucessMessage(inpackage.GetSession(), Encoding.Default.GetString(Globle.user.DIC_USERINFO["USERNAME"]), inpackage.GetUsername());
                    //打入最后一个封包片
                    TYPE_DETACH_PACKAGE TDME = new TYPE_DETACH_PACKAGE();
                    TDME.PackageId = inpackage.GetPackageId();
                    TDME.Content = inpackage.GetDetachMessage();
                    temp_message.Members.Add(TDME);
                    //进行丢包率测试
                    int[] LosePackageId = temp_message.CheckPackage();
                    if (LosePackageId.Length > (int)(inpackage.GetTotalPackageCount() * 0.2))
                    {
                        //损失太大 --> 抛弃整包
                        Globle.LIST_DetachMessageCollection.Remove(temp_message);
                    }
                    else if (LosePackageId.Length <= 0)
                    {
                        //拼装聊天封包片
                        int TotalSize = 0;
                        //得到大小
                        foreach (TYPE_DETACH_PACKAGE pck in temp_message.Members)
                        {
                            TotalSize += pck.Content.Length;
                        }
                        //开始拼装
                        byte[] DetachMessage = new byte[TotalSize];
                        Offset = 0;
                        foreach (TYPE_DETACH_PACKAGE pck in temp_message.Members)
                        {
                            Array.ConstrainedCopy(pck.Content, 0, DetachMessage, Offset, pck.Content.Length);
                            Offset += pck.Content.Length;
                        }

                        Globle.LIST_DetachMessageCollection.Remove(temp_message);
                        ChatViewModel.ReadTalkMessage(Encoding.Default.GetString(DetachMessage).Replace("|", " ").Replace("(*Equ*)", "=").Replace("*@^@*", ""), temp_message.Username, temp_message.SendTime.ToShortTimeString(), temp_message.Friendusername, temp_message.Session);
                    }
                    else
                    {
                        //丢包重传策略 [后续添加]
                        Globle.LIST_DetachMessageCollection.Remove(temp_message);
                    }
                }
                //封包中的某个封包片 --> 直接插入
                else if (inpackage.GetPackageId() < inpackage.GetTotalPackageCount())
                {
                    TYPE_DETACH_PACKAGE TDME = new TYPE_DETACH_PACKAGE();
                    TDME.PackageId = inpackage.GetPackageId();
                    TDME.Content = inpackage.GetDetachMessage();
                    temp_message.Members.Add(TDME);
                }
                else
                {
                    throw new Exception("封包片数量异常");
                }
            }
            //没找到
            else
            {
                TYPE_DETACH_MESSAGE TDME = new TYPE_DETACH_MESSAGE(inpackage.GetSession());
                TDME.Username = inpackage.GetUsername();
                TDME.Friendusername = inpackage.GetFriendName();
                TDME.SendTime = DateTime.Now;
                TDME.Total_PackageCount = inpackage.GetTotalPackageCount();
                Globle.LIST_DetachMessageCollection.Add(TDME);
                TYPE_DETACH_PACKAGE TDPE = new TYPE_DETACH_PACKAGE();
                TDPE.PackageId = inpackage.GetPackageId();
                TDPE.Content = inpackage.GetDetachMessage();
                //加入首封包片
                TDME.Members.Add(TDPE);
            }
        }

        /// <summary>
        ///     回复成功接收聊天信息
        /// </summary>
        /// <param name="Session" type="string">
        ///     <para>
        ///         当前聊天会话ID
        ///     </para>
        /// </param>
        /// <param name="Username" type="string">
        ///     <para>
        ///         用户名
        ///     </para>
        /// </param>
        /// <param name="FriendUsername" type="string">
        ///     <para>
        ///         好友用户名
        ///     </para>
        /// </param>
        public static void ACK_SucessMessage(String session, String username, String FriendUsername)
        {
            Friend friend = Globle.friendCollection.GetMemberByKey(FriendUsername) as Friend;
            if (friend != null && friend.OnlineState)
            {
                byte[] Username = Encoding.Default.GetBytes(username);
                byte[] UsernameLength = BitConverter.GetBytes(Username.Length);
                byte[] FriendName = Encoding.Default.GetBytes(FriendUsername);
                byte[] FriendNameLength = BitConverter.GetBytes(FriendName.Length);
                byte[] Session = Encoding.Default.GetBytes(session);
                byte[] SessionLength = BitConverter.GetBytes(Session.Length);
                byte[] IPAddress = Encoding.Default.GetBytes(Dns.GetHostAddresses(Dns.GetHostName())[0].ToString());
                byte[] IPLength = BitConverter.GetBytes(IPAddress.Length);
                byte[] TalkPort = BitConverter.GetBytes(Globle.user.TALK_PORT);
                byte[] None = new byte[2];
                byte[] PackageBody = new byte[Username.Length + FriendName.Length + Session.Length + IPAddress.Length + None.Length +20];
                Offset = 0;
                //用户名长度
                Array.ConstrainedCopy(UsernameLength, 0, PackageBody, Offset, 4);
                Offset += 4;
                //用户名
                Array.ConstrainedCopy(Username, 0, PackageBody, Offset, Username.Length);
                Offset += Username.Length;
                //好友用户名长度
                Array.ConstrainedCopy(FriendNameLength, 0, PackageBody, Offset, 4);
                Offset += 4;
                //好友用户名
                Array.ConstrainedCopy(FriendName, 0, PackageBody, Offset, FriendName.Length);
                Offset += FriendName.Length;
                //会话ID长度
                Array.ConstrainedCopy(SessionLength, 0, PackageBody, Offset, 4);
                Offset += 4;
                //会话ID
                Array.ConstrainedCopy(Session, 0, PackageBody, Offset, Session.Length);
                Offset += Session.Length;
                //空白 
                Array.ConstrainedCopy(None, 0, PackageBody, Offset, None.Length);
                Offset += 2;
                //IP地址长度
                Array.ConstrainedCopy(IPLength, 0, PackageBody, Offset, IPLength.Length);
                Offset += 4;
                //IP地址
                Array.ConstrainedCopy(IPAddress, 0, PackageBody, Offset, IPAddress.Length);
                Offset += IPAddress.Length;
                //聊天端口
                Array.ConstrainedCopy(TalkPort, 0, PackageBody, Offset, TalkPort.Length);
                byte[] protocol1 = ProtocolFactory.ProtocolFactory.GetProtocol("ReplySucessTalkMessage",
                                                                       (int)Packet.Protocol.TALK_OUT_NetworkCommand.SUCESS_TALK_MESSAGE,
                                                                       (int)Packet.Protocol.NetworkProtocol.TALK_MESSAGE, PackageBody,
                                                                       ProtocolFactory.ProtocolFactory.ACK.No,
                                                                       ProtocolFactory.ProtocolFactory.ENCRYPT.No,
                                                                       Globle.user.SESSION_CODE);
                //发送请求
                NetControl.Send(protocol1, friend.TalkPort, friend.IpAddress);
            }
        }

        /// <summary>
        ///     向好友发送提取图片请求包
        /// </summary>
        /// <param name="username" type="string">
        ///     <para>
        ///         用户名
        ///     </para>
        /// </param>
        /// <param name="FriendUsrename" type="string">
        ///     <para>
        ///         好友用户名
        ///     </para>
        /// </param>
        /// <param name="Pop_Picture_Code" type="string">
        ///     <para>
        ///         图片提取码
        ///     </para>
        /// </param>
        /// <param name="Pop_Picture_Code" type="string">
        ///     <para>
        ///         本次会话ID
        ///     </para>
        /// </param>
        /// <param name="PID" type="string">
        ///     <para>
        ///         本次图片ID
        ///     </para>
        /// </param>
        /// <returns>
        ///     返回false, 标示请求失败
        /// </returns>
        public static bool RequestImage(String username,String FriendUsrename, String Pop_Picture_Code, String TalkSession, String PID)
        {
            Friend friend = Globle.friendCollection.GetMemberByKey(FriendUsrename) as Friend;
            if (friend != null && friend.OnlineState)
            {
                byte[] Username = Encoding.Default.GetBytes(username);
                byte[] FriendName = Encoding.Default.GetBytes(FriendUsrename);
                byte[] PictrueCode = Encoding.Default.GetBytes(Pop_Picture_Code);
                byte[] Session = Encoding.Default.GetBytes(TalkSession);
                byte[] IPAddress = Encoding.Default.GetBytes(Dns.GetHostAddresses(Dns.GetHostName())[0].ToString());
                byte[] UsernameLength = BitConverter.GetBytes(Username.Length);
                byte[] FriendNameLength = BitConverter.GetBytes(FriendName.Length);
                byte[] PictrueCodeLength = BitConverter.GetBytes(PictrueCode.Length);
                byte[] SessionLength = BitConverter.GetBytes(Session.Length);
                byte[] Pid = BitConverter.GetBytes(int.Parse(PID));
                byte[] IPLength = BitConverter.GetBytes(IPAddress.Length);
                byte[] TalkPort = BitConverter.GetBytes(Globle.user.TALK_PORT);
                byte[] packagebody = new byte[Username.Length + FriendName.Length + Session.Length + PictrueCode.Length + IPAddress.Length + 28];
                Offset = 0;
                Array.ConstrainedCopy(UsernameLength, 0, packagebody, Offset, 4);
                Offset += 4;
                Array.ConstrainedCopy(Username, 0, packagebody, Offset, Username.Length);
                Offset += Username.Length;
                Array.ConstrainedCopy(FriendNameLength, 0, packagebody, Offset, 4);
                Offset += 4;
                Array.ConstrainedCopy(FriendName, 0, packagebody, Offset, FriendName.Length);
                Offset += FriendName.Length;
                Array.ConstrainedCopy(SessionLength, 0, packagebody, Offset, 4);
                Offset += 4;
                Array.ConstrainedCopy(Session, 0, packagebody, Offset, Session.Length);
                Offset += Session.Length;
                Array.ConstrainedCopy(PictrueCodeLength, 0, packagebody, Offset, 4);
                Offset += 4;
                Array.ConstrainedCopy(PictrueCode, 0, packagebody, Offset, PictrueCode.Length);
                Offset += PictrueCode.Length;
                Array.ConstrainedCopy(IPLength, 0, packagebody, Offset, 4);
                Offset += 4;
                Array.ConstrainedCopy(IPAddress, 0, packagebody, Offset, IPAddress.Length);
                Offset += IPAddress.Length;
                Array.ConstrainedCopy(Pid, 0, packagebody, Offset, 4);
                Offset += 4;
                Array.ConstrainedCopy(TalkPort, 0, packagebody, Offset, 4);
                Offset += 4;
                byte[] protocol1 = ProtocolFactory.ProtocolFactory.GetProtocol("RequestPicture",
                                                                       (int)Packet.Protocol.TALK_OUT_NetworkCommand.REQUEST_PICTURE,
                                                                       (int)Packet.Protocol.NetworkProtocol.TALK_MESSAGE, 
                                                                       packagebody,
                                                                       ProtocolFactory.ProtocolFactory.ACK.No,
                                                                       ProtocolFactory.ProtocolFactory.ENCRYPT.No,
                                                                       Globle.user.SESSION_CODE);
                //发送请求
                NetControl.Send(protocol1, friend.TalkPort, friend.IpAddress);
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        ///     卸载指定通话的超时器
        /// </summary>
        /// <param name="inpackage" type="Hi_Baidu.Packet.InPacket.TalkInPacket.AckSucessfulTalkMessagePacket">
        ///     <para>
        ///         通话成功回馈包
        ///     </para>
        /// </param>
        public static void UnInstallTimer_SucessfulTalkMessage(AckSucessfulTalkMessagePacket inpackage)
        {
            //卸载本次通话超时器
            Globle.timeoutTimerManager.RemoveTimer(inpackage.GetTalkSession());
        }

        /// <summary>
        ///     发送提取的图片
        /// </summary>
        /// <param name="inpackage" type="Hi_Baidu.Packet.InPacket.TalkInPacket.RequestPicturePacket">
        ///     <para>
        ///         图片提取请求包   
        ///     </para>
        /// </param>
        public static void ReSendRequestImage(RequestPicturePacket inpackage)
        {
            PopPictureCache popPictureCache = DeclareCacheManager.popPictureCacheManager.GetMemberByKey(inpackage.GetRequestPicId()) as PopPictureCache;
            //分片发送图片信息包
            if (popPictureCache != null)
            {
                //发送失败
                if (!ReSendRequestImage(inpackage, popPictureCache))
                {
                }
                //发送成功
                else
                {
                    return;
                }
            }
            //发送提取图片过期信息包
        }

        /// <summary>
        ///     发送请求的图片
        /// </summary>
        /// <param name="inpackage" type="Hi_Baidu.Packet.InPacket.TalkInPacket.RequestPicturePacket">
        ///     <para>
        ///         图片请求包
        ///     </para>
        /// </param>
        /// <param name="RequestFileCache" type="Hi_Baidu.Cache.CacheObject.PopPictureCache">
        ///     <para>
        ///         图片缓存
        ///     </para>
        /// </param>
        /// <returns>
        ///     返回false, 标示发送失败
        /// </returns>
        public static bool ReSendRequestImage(RequestPicturePacket inpackage, PopPictureCache RequestFileCache)
        {
            Friend friend = Globle.friendCollection.GetMemberByKey(inpackage.GetUsername()) as Friend;
            //图片文件缓存
            if (RequestFileCache.PictureType == PopPictureCache.PopType.File)
            {
                //如果文件存在
                if (File.Exists(RequestFileCache.Value) && friend != null && friend.OnlineState)
                {
                    using (FileStream FS_Image = new FileStream(RequestFileCache.Value, FileMode.Open, FileAccess.Read))
                    {
                        byte[] ImageContent = new byte[512];
                        //当前读取的字节数
                        int ReadCount = 0;
                        //当前封包片ID
                        int PackageId = 1;
                        //当前封包封包片数目
                        int TotalPackageCount = (int)FS_Image.Length / 512;
                        byte[] temp_Content = new byte[FS_Image.Length];
                        FS_Image.Read(temp_Content, 0, temp_Content.Length);
                        FS_Image.Position = 0;
                        //----------------------------------------测试用--------------------------------
                        //MemoryStream ms = new MemoryStream();
                        //ms.Write(temp_Content, 0, temp_Content.Length);
                        //System.Drawing.Image img = System.Drawing.Image.FromStream(ms);

                        //----------------------------------------------------------------------------------
                        int TotalLength = Convert.ToBase64String(temp_Content).Length;
                        double _Count = FS_Image.Length / 512.00;
                        int _temp = (int)_Count;
                        if (_Count > _temp && _Count < _temp + 1)
                        {
                            TotalPackageCount = _temp + 1;
                        }
                        else
                        {
                            TotalPackageCount = _temp;
                        }
                        byte[] protocol1 = null;
                        //开始读取
                        while ((ReadCount = FS_Image.Read(ImageContent, 0, ImageContent.Length)) > 0)
                        {
                            Byte[] RealData = new Byte[ReadCount];
                            Array.Copy(ImageContent, RealData, ReadCount);
                            //得到协议
                            protocol1 = ProtocolFactory.ProtocolFactory.DetachImageProtocol(
                                "DetachImage",
                                (int)Protocol.TALK_OUT_NetworkCommand.DETACH_IMAGE,
                                (int)Protocol.NetworkProtocol.TALK_MESSAGE,
                                Globle.user.DIC_USERINFO["USERNAME"],
                                Encoding.Default.GetBytes(friend.Username),
                                Encoding.Default.GetBytes(inpackage.GetTalkSession()),
                                RealData,
                                BitConverter.GetBytes(int.Parse(inpackage.GetPID())),
                                BitConverter.GetBytes(TotalLength),
                                BitConverter.GetBytes(PackageId),
                                BitConverter.GetBytes(TotalPackageCount),
                                ProtocolFactory.ProtocolFactory.ACK.No,
                                ProtocolFactory.ProtocolFactory.ENCRYPT.No);
                            //发送当前封包片
                            NetControl.Send(protocol1, friend.TalkPort, friend.IpAddress);
                            PackageId++;
                            Thread.Sleep(1);
                            ImageContent = new byte[512];
                        }
                    }
                    return true;
                }
                else
                {
                    return false;
                }
            }
            //图片流缓存
            else
            {
                using (MemoryStream MS_PictureStream = new MemoryStream())
                {
                    //将图片保存在流中
                    RequestFileCache.PictureStream.Save(MS_PictureStream, System.Drawing.Imaging.ImageFormat.Bmp);
                    MS_PictureStream.Position = 0;

                    byte[] ImageContent = new byte[512];
                    //当前读取的字节数
                    int ReadCount = 0;
                    //当前封包片ID
                    int PackageId = 1;
                    //当前封包封包片数目
                    int TotalPackageCount = (int)MS_PictureStream.Length / 512;
                    byte[] temp_Content = new byte[MS_PictureStream.Length];
                    MS_PictureStream.Read(temp_Content, 0, temp_Content.Length);
                    MS_PictureStream.Position = 0;
                    //----------------------------------------测试用--------------------------------
                    //MemoryStream ms = new MemoryStream();
                    //ms.Write(temp_Content, 0, temp_Content.Length);
                    //System.Drawing.Image img = System.Drawing.Image.FromStream(ms);

                    //----------------------------------------------------------------------------------
                    int TotalLength = Convert.ToBase64String(temp_Content).Length;
                    double _Count = MS_PictureStream.Length / 512.00;
                    int _temp = (int)_Count;
                    if (_Count > _temp && _Count < _temp + 1)
                    {
                        TotalPackageCount = _temp + 1;
                    }
                    else
                    {
                        TotalPackageCount = _temp;
                    }
                    byte[] protocol1 = null;
                    //开始读取
                    while ((ReadCount = MS_PictureStream.Read(ImageContent, 0, ImageContent.Length)) > 0)
                    {
                        Byte[] RealData = new Byte[ReadCount];
                        Array.Copy(ImageContent, RealData, ReadCount);
                        //得到协议
                        protocol1 = ProtocolFactory.ProtocolFactory.DetachImageProtocol(
                            "DetachImage",
                            (int)Protocol.TALK_OUT_NetworkCommand.DETACH_IMAGE,
                            (int)Protocol.NetworkProtocol.TALK_MESSAGE,
                            Globle.user.DIC_USERINFO["USERNAME"],
                            Encoding.Default.GetBytes(friend.Username),
                            Encoding.Default.GetBytes(inpackage.GetTalkSession()),
                            RealData,
                            BitConverter.GetBytes(int.Parse(inpackage.GetPID())),
                            BitConverter.GetBytes(TotalLength),
                            BitConverter.GetBytes(PackageId),
                            BitConverter.GetBytes(TotalPackageCount),
                            ProtocolFactory.ProtocolFactory.ACK.No,
                            ProtocolFactory.ProtocolFactory.ENCRYPT.No);
                        //发送当前封包片
                        NetControl.Send(protocol1, friend.TalkPort, friend.IpAddress);
                        PackageId++;
                        Thread.Sleep(1);
                        ImageContent = new byte[512];
                    }
                    return true;
                }
            }
        }

        /// <summary>
        ///     处理分片图片数据
        /// </summary>
        /// <param name="inpackage" type="Hi_Baidu.Packet.InPacket.TalkInPacket.Detach_TalkImagePacket">
        ///     <para>
        ///         分片图片数据包
        ///     </para>
        /// </param>
        public static void ProcessDetachImage(Detach_TalkImagePacket inpackage)
        {
            bool IS_FOUND = false;
            TYPE_DETACH_IMAGE_MESSAGE temp_message = null;
            foreach (TYPE_DETACH_IMAGE_MESSAGE message in Globle.LIST_DetachImageCollection)
            {
                if (message.Session == inpackage.GetSession() && message.PID == inpackage.GetPID())
                {
                    IS_FOUND = true;
                    temp_message = message;
                    break;
                }
            }
            //找到了
            if (IS_FOUND)
            {
                //最后一个封包片 --> 插入
                if (inpackage.GetPackageId() == inpackage.GetTotalPackageCount())
                {
                    //ChatProcessModel.ACK_SucessMessage(inpackage.GetSession(), Encoding.Default.GetString(Globle.user.DIC_USERINFO["USERNAME"]), inpackage.GetUsername());
                    //打入最后一个封包片
                    TYPE_DETACH_IMAGE_PACKAGE TDME = new TYPE_DETACH_IMAGE_PACKAGE();
                    TDME.PackageId = inpackage.GetPackageId();
                    TDME.Content = inpackage.GetDetachImageData();
                    TDME.Length = inpackage.GetPackageLength();
                    temp_message.Members.Add(TDME);
                    //进行丢包率测试
                    int[] LosePackageId = temp_message.CheckPackage();
                    if (LosePackageId.Length > (int)(inpackage.GetTotalPackageCount() * 0.2))
                    {
                        //损失太大 --> 抛弃整包
                        Globle.LIST_DetachImageCollection.Remove(temp_message);
                    }
                    else if (LosePackageId.Length <= 0)
                    {
                        //拼装聊天封包片
                        byte[] img = new byte[temp_message.TotalLength];
                        int Index = 0;
                        foreach (TYPE_DETACH_IMAGE_PACKAGE pck in temp_message.Members)
                        {
                            Array.Copy(pck.Content, 0, img, Index, pck.Length - 1);
                            Index += pck.Length - 1;
                        }
                        MemoryStream MS = new MemoryStream();
                        MS.Write(img, 0, temp_message.TotalLength);
                        MS.Position = 0;
                        System.Drawing.Image img_User = System.Drawing.Image.FromStream(MS, false, true);
                        ChatViewModel.AppendDetachImageToUserTalkWindow(img_User, temp_message);
                        Globle.LIST_DetachImageCollection.Remove(temp_message);
                        //ChatViewModel.ReadTalkMessage(MessageContent, temp_message.Username, temp_message.SendTime.ToShortTimeString(), temp_message.Friendusername, temp_message.Session);
                    }
                    else
                    {
                        //丢包重传策略 [后续添加]
                        Globle.LIST_DetachImageCollection.Remove(temp_message);
                    }
                }
                //封包中的某个封包片 --> 直接插入
                else if (inpackage.GetPackageId() < inpackage.GetTotalPackageCount())
                {
                    TYPE_DETACH_IMAGE_PACKAGE TDME = new TYPE_DETACH_IMAGE_PACKAGE();
                    TDME.PackageId = inpackage.GetPackageId();
                    TDME.Content = inpackage.GetDetachImageData();
                    TDME.Length = inpackage.GetPackageLength();
                    temp_message.Members.Add(TDME);
                }
                else
                {
                    throw new Exception("封包片数量异常");
                }
            }
            //没找到
            else
            {
                TYPE_DETACH_IMAGE_MESSAGE TDME = new TYPE_DETACH_IMAGE_MESSAGE(inpackage.GetSession());
                TDME.TotalLength = inpackage.GetTotalLength();
                TDME.PID = inpackage.GetPID();
                TDME.Username = inpackage.GetUsername();
                TDME.Friendusername = inpackage.GetFriendName();
                TDME.SendTime = inpackage.TalkPackage.SendTime;
                TDME.Total_PackageCount = inpackage.GetTotalPackageCount();
                Globle.LIST_DetachImageCollection.Add(TDME);
                TYPE_DETACH_IMAGE_PACKAGE TDPE = new TYPE_DETACH_IMAGE_PACKAGE();
                TDPE.PackageId = inpackage.GetPackageId();
                TDPE.Content = inpackage.GetDetachImageData();
                TDPE.Length = inpackage.GetPackageLength();
                //加入首封包片
                TDME.Members.Add(TDPE);
            }
        }

        /// <summary>
        ///     向好友发送窗口抖动请求
        /// </summary>
        /// <param name="username" type="byte[]">
        ///     <para>
        ///         用户名
        ///     </para>
        /// </param>
        /// <param name="friend" type="Hi_Baidu.Entry.CollectionObject.Friend">
        ///     <para>
        ///         好友对象
        ///     </para>
        /// </param>
        public static void SendWindowShadow(byte[] username, Friend friend)
        {
            //发送窗口抖动请求
            byte[] UsernameLength = BitConverter.GetBytes(username.Length);
            byte[] packagebody = new byte[username.Length + 4];
            Offset = 0;
            Array.ConstrainedCopy(UsernameLength, 0, packagebody, Offset, 4);
            Offset += 4;
            Array.ConstrainedCopy(username, 0, packagebody, Offset, username.Length);
            Offset += username.Length;
            String TALK_SESSION = Encrypt_HASH.HashString(DateTime.Now.ToString() + ":" + friend.Username);
            //通过命令工厂得到命令协议
            byte[] protocol1 = ProtocolFactory.ProtocolFactory.ReGetProtocolToTalkMessage("WindowShadow",
                                                                   (int)Packet.Protocol.TALK_OUT_NetworkCommand.WINDOW_SHADOW,
                                                                   (int)Packet.Protocol.NetworkProtocol.TALK_MESSAGE,
                                                                   packagebody,
                                                                   ProtocolFactory.ProtocolFactory.ACK.Yes,
                                                                   ProtocolFactory.ProtocolFactory.ENCRYPT.No,
                                                                   TALK_SESSION);
            NetControl.Send(protocol1, friend.TalkPort, friend.IpAddress);
            //打入超时队列
            WindowShadowTimeOutEvent WSTE = new WindowShadowTimeOutEvent(friend, "WindowShadow - " + TALK_SESSION, 5000, 1);
            Globle.timeoutTimerManager.InstallTimer(WSTE);
        }

        /// <summary>
        ///     回馈指定用户成功的抖动窗口请求
        /// </summary>
        /// <param name="inpackage" type="Hi_Baidu.Packet.InPacket.TalkInPacket.WindowShadowPacket">
        ///     <para>
        ///         抖动窗口请求包
        ///     </para>
        /// </param>
        public static void ACK_SucessfulWindowShadow(WindowShadowPacket inpackage)
        {
            Friend friend = Globle.friendCollection.GetMemberByKey(inpackage.GetUsername()) as Friend;
            if (friend != null && friend.OnlineState)
            {
                byte[] username = Globle.user.DIC_USERINFO["USERNAME"];
                //发送窗口抖动请求
                byte[] UsernameLength = BitConverter.GetBytes(username.Length);
                byte[] packagebody = new byte[username.Length + 4];
                Offset = 0;
                Array.ConstrainedCopy(UsernameLength, 0, packagebody, Offset, 4);
                Offset += 4;
                Array.ConstrainedCopy(username, 0, packagebody, Offset, username.Length);
                Offset += username.Length;
                String TALK_SESSION = Encrypt_HASH.HashString(DateTime.Now.ToString() + ":" + friend.Username);
                //通过命令工厂得到命令协议
                byte[] protocol1 = ProtocolFactory.ProtocolFactory.ReGetProtocolToTalkMessage("ReplyWindowShadow",
                                                                       (int)Packet.Protocol.TALK_OUT_NetworkCommand.ACK_WAINDOW_SHADOW,
                                                                       (int)Packet.Protocol.NetworkProtocol.TALK_MESSAGE,
                                                                       packagebody,
                                                                       ProtocolFactory.ProtocolFactory.ACK.No,
                                                                       ProtocolFactory.ProtocolFactory.ENCRYPT.No,
                                                                       inpackage.GetSession());
                NetControl.Send(protocol1, friend.TalkPort, friend.IpAddress);
            }
        }

        /// <summary>
        ///     处理窗口抖动请求
        /// </summary>
        /// <param name="inpackage" type="Hi_Baidu.Packet.InPacket.TalkInPacket.WindowShadowPacket">
        ///     <para>
        ///         窗口抖动请求包
        ///     </para>
        /// </param>
        public static void ProcessWindowShadow(WindowShadowPacket inpackage)
        {
            //回馈抖动窗口接收响应
            ChatProcessModel.ACK_SucessfulWindowShadow(inpackage);
            //开始搜寻指定窗口
            Win_TalkWindow win_TalkWindow = Globle.popWindowManager.GetMemberByKey(inpackage.GetUsername()) as Win_TalkWindow;
            if (win_TalkWindow != null)
            {
                ChatViewModel.MakeWindowShadow(win_TalkWindow);
            }
        }

        /// <summary>
        ///    附加成功抖动窗口请求后的消息
        /// </summary>
        /// <param name="inpackage" type="Hi_Baidu.Packet.InPacket.TalkInPacket.AckSucessfulWindowShadowPacket">
        ///     <para>
        ///         成功抖动窗口请求包
        ///     </para>
        /// </param>
        public static void ACK_WindowShadow(AckSucessfulWindowShadowPacket inpackage)
        {
            //卸载相应超时器
            Globle.timeoutTimerManager.RemoveTimer("WindowShadow - " + inpackage.GetSession());
            //提示用户请求成功
            Win_TalkWindow win_TalkWindow = Globle.popWindowManager.GetMemberByKey(inpackage.GetUsername()) as Win_TalkWindow;
            //找寻目标窗口，并且存在
            if (win_TalkWindow != null)
            {
                ChatViewModel.AppendSendShadowSucessful(win_TalkWindow, "发送窗口抖动效果成功。");
            }
        }
    }
}
